package com.zd.common.common.utils;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.imageio.ImageIO;

import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.thoughtworks.xstream.core.util.Base64Encoder;

import sun.misc.BASE64Encoder;

/**
 * Created by mocaijin on 16/01/2018.
 */
public class QrCodeCreateUtil {

    /**
     * @param filePath   二维码文件生成路径
     * @param fileName   二维码文件名
     * @param content    二维码文件内容
     * @param fileFormat 二维码文件格式
     * @param width      图像宽度
     * @param height     图像高度
     */
    public static void generateQrCode(String filePath, String fileName, String content, String fileFormat, int width, int height) throws Exception {
        JSONObject json = new JSONObject();
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵
        Path path = FileSystems.getDefault().getPath(filePath, fileName);
        MatrixToImageWriter.writeToPath(bitMatrix, fileFormat, path);// 输出图像
    }

    /**
     * 二维码生成器
     *
     * @param text 二维码内容
     * @throws IOException
     */
    public static String generalQRCode(String text) {
        Hashtable hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        String binary = null;

        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(text,
                    BarcodeFormat.QR_CODE, 200, 200, hints);

            // 实现一： 输出图片到指定目录
            // File outputFile = new File("d://1.jpg");
            // MatrixToImageWriter.writeToFile(bitMatrix, "png", outputFile);

            // 实现二：生成二维码图片并将图片转为二进制传递给前台
            // 1、读取文件转换为字节数组
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            BufferedImage image = toBufferedImage(bitMatrix);
            // //
            ImageIO.write(image, "png", out);
            byte[] bytes = out.toByteArray();
            
            // 2、将字节数组转为二进制
            BASE64Encoder encoder = new BASE64Encoder();
            binary = encoder.encodeBuffer(bytes).trim();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return binary;
    }
    
    /**
     * 二维码生成器
     *
     * @param text 二维码内容
     * @throws IOException
     */
    public static String generalQRCodeText(String qrCode,String text) {
        Hashtable hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        String binary = null;

        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(qrCode,
                    BarcodeFormat.QR_CODE, 200, 200, hints);

            // 实现一： 输出图片到指定目录
            // File outputFile = new File("d://1.jpg");
            // MatrixToImageWriter.writeToFile(bitMatrix, "png", outputFile);

            // 实现二：生成二维码图片并将图片转为二进制传递给前台
            // 1、读取文件转换为字节数组
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            BufferedImage image = toBufferedImage(bitMatrix);
            
            
            BufferedImage outImage = new BufferedImage(200, 230, BufferedImage.TYPE_INT_RGB);
            Graphics2D outg = outImage.createGraphics();
            outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
            outg.setColor(Color.BLACK); 
            outg.setFont(new Font("微软雅黑",Font.BOLD,30)); //字体、字型、字号 ++
            int strWidth = outg.getFontMetrics().stringWidth(text);
            outg.setColor(Color.WHITE); 
            outg.drawImage(outImage, 0,0,200,230,Color.WHITE , null);
            outg.drawString(text, 100  - strWidth/2 , image.getHeight() + (outImage.getHeight() - image.getHeight())/2 + 12 );

            outg.dispose(); 
            outImage.flush();
            image = outImage;
            
            image = rotateHorizon(image);
            image = rotateCounterclockwise90(image);
            
            ImageIO.write(image, "jpg", out);
            byte[] bytes = out.toByteArray();
            File file=new File("D:\\tts9/"+ text +".jpg");

            // 2、将字节数组转为二进制
            BASE64Encoder encoder = new BASE64Encoder();
            binary = encoder.encodeBuffer(bytes).trim();
            
            Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");  
            Method mainMethod= clazz.getMethod("decode", String.class);  
            mainMethod.setAccessible(true);  
             Object retObj=mainMethod.invoke(null, binary);  
            byte[] result = (byte[]) retObj;
            FileOutputStream fos = new FileOutputStream(file);  
            BufferedOutputStream bos = new BufferedOutputStream(fos);  
            bos.write(result);  
            bos.close();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return binary;
    }

    
    public static BufferedImage rotateHorizon(BufferedImage bi) {//水平翻转
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(width,height,bi.getType());
		for (int i = 0; i < width; i++)
			for (int j = 0; j < height; j++)
				bufferedImage.setRGB( width - i-1,j, bi.getRGB(i, j));
		return bufferedImage;
	}

    public static BufferedImage rotateCounterclockwise90(BufferedImage bi) {//逆时针旋转90度
		int width = bi.getWidth();
		int height = bi.getHeight();
		BufferedImage bufferedImage = new BufferedImage(height, width, bi.getType());
		for (int i = 0; i < width; i++)
			for (int j = 0; j < height; j++)
				bufferedImage.setRGB(j, i, bi.getRGB(i, j));
		return bufferedImage;
	}



    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }

        return image;
    }

}
